package com.hdax.dm.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdax.dm.base.Image;
import com.hdax.dm.dto.*;
import com.hdax.dm.feign.ImageFeign;
import com.hdax.dm.feign.SchedulerFeign;
import com.hdax.dm.item.DmCinema;
import com.hdax.dm.item.Item;
import com.hdax.dm.item.ItemType;
import com.hdax.dm.mappers.ItemMapper;
import com.hdax.dm.mapstructs.IndexNavDtoMapper;
import com.hdax.dm.mapstructs.ItemsDtoMapper;
import com.hdax.dm.scheduler.DmScheduler;
import com.hdax.dm.scheduler.DmSchedulerSeatPrice;
import com.hdax.dm.service.ItemService;
import com.hdax.dm.utils.response.CommonResponse;
import com.hdax.dm.utils.response.ResponseUtils;
import com.hdax.dm.vo.ItemSearchVo;
import io.netty.util.internal.StringUtil;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Service
public class ItemServiceImpl extends ServiceImpl<ItemMapper,Item> implements ItemService {

    @Autowired
    private ImageFeign imageFeign;

    @Autowired
    private IndexNavDtoMapper indexNavDtoMapper;

    @Autowired
    private ItemsDtoMapper itemsDtoMapper;

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private SchedulerFeign schedulerFeign;

    @Resource
    private RedisTemplate redisTemplate;
    @Override//8个导航内商品
    public List<IndexNavDto.HotItems> hotItems(Long itemType1Id, Long isBanner) {
            List<Item> items = baseMapper.hotItems(itemType1Id, isBanner);
            List<IndexNavDto.HotItems> hotItems = new ArrayList<>();

            items.forEach(item -> {
                IndexNavDto.HotItems hot = new IndexNavDto.HotItems();
                hot.setId(item.getId());
                hot.setItemName(item.getItemName());
                hot.setMinPrice(item.getMinPrice());
                //通过openfeign远程调用获取图片信息
                Image image = imageFeign.image(hot.getId(), 2L, 1L);
                String imgurl = image == null ? "" : image.getImgUrl();
                hot.setImgUrl(imgurl);
                hotItems.add(hot);
            });
        return hotItems;
    }

    @Override//今日推荐
    public CommonResponse<List<IndexNavDto.HotItems>> recommend() {
        QueryWrapper<Item> wrapper = new QueryWrapper<>();
        wrapper.eq("isRecommend",1L);
        //日期实例化获取当前年月日
        LocalDate now = LocalDate.from(LocalDate.now());
        String datetime = String.valueOf(now);

        wrapper.last("ORDER BY\n" +
                "startTime DESC");
        IPage<Item> iPage = page(Page.of(1L,6L),wrapper);
        List<Item> items = iPage.getRecords();
        List<IndexNavDto.HotItems> hotItems = indexNavDtoMapper.toHotItems(items);
        for (IndexNavDto.HotItems hot: hotItems) {
            Image image = imageFeign.image(hot.getId(), 0L,1L);
            String imgurl = image==null ? "":image.getImgUrl();
            hot.setImgUrl(imgurl);

        }

        return ResponseUtils.returnSuccess(hotItems);
    }

    @Override//即将开售
    public CommonResponse<List<IndexNavDto.HotItems>> sellItems() {

        List<IndexNavDto.HotItems> hotItems =null;
        if(redisTemplate.opsForValue().get("sellItems")!=null){
            hotItems = (List<IndexNavDto.HotItems>) redisTemplate.opsForValue().get("sellItems");
        }else {
            List<Item> items =  baseMapper.sellItems();
            hotItems = indexNavDtoMapper.toHotItems(items);
            for (IndexNavDto.HotItems hot: hotItems) {
                Image image = imageFeign.image(hot.getId(), 0L,1L);
                String imgurl = image==null ? "":image.getImgUrl();
                hot.setImgUrl(imgurl);
            }
            redisTemplate.opsForValue().set("sellItems",hotItems);
        }
        return ResponseUtils.returnSuccess(hotItems);
    }
    @Override//楼层
    public CommonResponse<List<IndexFloorDto>> Floors() {

        List<ItemType> itemTypes = baseMapper.typeItems();
        List<IndexFloorDto> floor = new ArrayList<>();
        if(redisTemplate.opsForValue().get("floors")!=null) {
            floor = (List<IndexFloorDto>) redisTemplate.opsForValue().get("floors");
        }else {
            List<IndexFloorDto> floorDtos = new ArrayList<>();
            itemTypes.forEach(type ->{
            QueryWrapper<Item> wrapper = new QueryWrapper<>();
            IndexFloorDto dto = new IndexFloorDto();
            dto.setIndex(type.getId());
            dto.setItemTypeName(type.getItemType());
            wrapper.eq("itemType1Id",type.getId());
            wrapper.last("limit 5");
            List<Item> items = baseMapper.selectList(wrapper);
            dto.setItemTypeId(type.getId());
            List<IndexFloorDto.FloorItems> floorItemsList = new ArrayList<>();
            int i =0;
                for (Item item : items) {
                    List<DmCinema> dmCinemas = baseMapper.dmCinemas(item.getCinemaId());
                    IndexFloorDto.FloorItems floorItem = new IndexFloorDto.FloorItems();
                    dmCinemas.forEach(dmCinema -> {
                        floorItem.setId(item.getId());
                        floorItem.setItemName(item.getItemName());
                        floorItem.setAreaId(dmCinema.getAreaId());
                        floorItem.setAreaName(dmCinema.getAreaName());
                        floorItem.setAddress(dmCinema.getAddress());
                        floorItem.setStartDate(item.getStartTime());
                        floorItem.setEndDate(item.getEndTime());
                        floorItem.setMinPrice(item.getMinPrice());
                    });
                    Image image = imageFeign.image(item.getId(),0L,1L);
                    String imgurl = image==null ? "/static/img/pic3.jpg":image.getImgUrl();
                    floorItem.setImgUrl(imgurl);
                    floorItemsList.add(floorItem);
                }
            dto.setItems(floorItemsList);
            floorDtos.add(dto);
            });
            floor = floorDtos;
            //redis存入
            redisTemplate.opsForValue().set("floors",floor);
        }

        return ResponseUtils.returnSuccess(floor);
    }


    @Override//首页楼层右侧10条内容
    public CommonResponse<List<IndexFloorDto.FloorItems>> senioritys(Long itemTypeId) {
        QueryWrapper<Item> wrapper = new QueryWrapper<>();
        if(itemTypeId>=20){
            wrapper.eq("itemType2Id",itemTypeId);
        }else if (itemTypeId>0){
            wrapper.eq("itemType1Id",itemTypeId);
        }
        wrapper.last("Limit 10");
        List<IndexFloorDto.FloorItems> floorItem = null;
            List<Item> items = baseMapper.selectList(wrapper);
            List<IndexFloorDto.FloorItems> floorItems = new ArrayList<>();
            items.forEach(item -> {
                IndexFloorDto.FloorItems floor = new IndexFloorDto.FloorItems();
                floor.setId(item.getId());
                floor.setItemName(item.getItemName());
                floor.setMinPrice(item.getMinPrice());
                floor.setEndDate(item.getEndTime());
                floor.setStartDate(item.getStartTime());
                List<DmCinema> dmCinemas = baseMapper.dmCinemas(item.getCinemaId());
                dmCinemas.forEach(dmCinema -> {
                    floor.setAreaId(dmCinema.getAreaId());
                    floor.setAreaName(dmCinema.getAreaName());
                });
                Image image = imageFeign.image(item.getId(),0L,1L);
                String imgurl = image==null ? "/static/img/pic3.jpg":image.getImgUrl();
                floor.setImgUrl(imgurl);
                floorItems.add(floor);
            });
            floorItem = floorItems;
        return ResponseUtils.returnSuccess(floorItem);
    }


    //二级页面
    @Override
    public CommonResponse<ItemsDto> itemsId(Long id) {
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("id",id);

        List<Item> items = baseMapper.selectList(wrapper);
        List<ItemsDto> itemsDtos = itemsDtoMapper.ToItemsDto(items);
        ItemsDto itemsDto = new ItemsDto();
        for (ItemsDto i: itemsDtos) {

            List<DmCinema> cinemas = baseMapper.dmCinemas(i.getCinemaId());
            for (DmCinema cli: cinemas) {
                i.setAreaId(cli.getAreaId());
                i.setAddress(cli.getAddress());
                i.setAreaName(cli.getAreaName());
            }
            Image image = imageFeign.image(i.getId(),0L,1L);
            String imgurl = image==null ? "":image.getImgUrl();
            i.setImgUrl(imgurl);
            itemsDto = i;
        }

        return ResponseUtils.returnSuccess(itemsDto);
    }

    @Override
    public List<Item> itemId(Long itemid) {
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("id",itemid);
        return list(wrapper);
    }

    //搜索内容展示
    public ItemSearchResultDto querygoodsinfos(ItemSearchVo vo) throws IOException {
        //ES搜索请求对象
        SearchRequest request = new SearchRequest("items");
        //搜索条件构造器，负责进行多条件拼装
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //语法高亮建造器
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //Elasticsearch多条件搜索
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        //由于页面的条件是不确定个数的，所以通过判断
        if(StringUtils.hasLength(vo.getKeyword())){
            //设置语法高亮
            HighlightBuilder.Field highlightField1 = new HighlightBuilder.Field("itemname");
            highlightField1.highlighterType("unified");
            HighlightBuilder.Field highlightField2 = new HighlightBuilder.Field("abstractmessage");
            highlightField2.highlighterType("unified");
            highlightBuilder.fields().add(highlightField1);
            highlightBuilder.fields().add(highlightField2);

            //拼接itemname的匹配度查询
            boolQueryBuilder.must(QueryBuilders.matchQuery("itemname",vo.getKeyword()));
            //should:不影响查询结果条数，但是影响排名评分
            boolQueryBuilder.should(QueryBuilders.matchQuery("abstractmessage",vo.getKeyword()));
        }


        //所在地区查询
        if(vo.getAreaId()!=0){
            boolQueryBuilder.must(QueryBuilders.termQuery("cinemaid",vo.getAreaId()));
        }
        //and
        //一二级分类
        if(vo.getItemTypeId1()!=0){
            boolQueryBuilder.must(QueryBuilders.termQuery("itemtype1id",vo.getItemTypeId1()));
        }
        if(vo.getItemTypeId2()!=0){
            boolQueryBuilder.must(QueryBuilders.termQuery("itemtype2id",vo.getItemTypeId2()));
        }

        //日期之间范围查找
        if(StringUtils.hasLength(vo.getStartTime()) && StringUtils.hasLength(vo.getEndTime())){
            RangeQueryBuilder rangeQueryBuilder =QueryBuilders.rangeQuery("starttime");
            rangeQueryBuilder.gte(vo.getStartTime().concat("00:00:00"));
            rangeQueryBuilder.lte(vo.getEndTime().concat("23:59:59"));
        }

        //排序查询
        //recentSell recentShow recommend
        //vo.getSort()
        String sortField = "isrecommend";//排序字段
        switch (vo.getSort()){
            case "recentSell": sortField = "createdtime";break;
            case "recommend": sortField = "isrecommend";break;
            case "recentShow": sortField = "starttime";break;
        }
        builder.sort(sortField, SortOrder.DESC);

        //执行查询封装
        builder.query(boolQueryBuilder);
        //设置高亮的样式
        highlightBuilder.requireFieldMatch(true);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        builder.highlighter(highlightBuilder);
        //分页查询
        //from 默认0  currentPage-1) * pageSize
        builder.from((vo.getCurrentPage()-1)*vo.getPageSize());
        builder.size(vo.getPageSize());
        request.source(builder);


        //ES响应对象
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //实例化对象，准备存入从es取到的内容
        ItemSearchResultDto resultDto = new ItemSearchResultDto();
        SearchHits hits = response.getHits();
        Long totalCount = hits.getTotalHits().value;//总条数
        resultDto.setTotal(totalCount);
        resultDto.setPageSize(vo.getPageSize());//每页条数
        resultDto.setCurrentPage(vo.getCurrentPage());//当前页码
        resultDto.setPageCount(totalCount % vo.getPageSize() == 0?totalCount / vo.getPageSize():totalCount / vo.getPageSize()+1);

        SearchHit[] searchHits = hits.getHits();
        for (int i = 0; i < searchHits.length; i++) {
            //每一行搜索到的商品数据
            ItemRowsDto rowsDto = JSON.parseObject(searchHits[i].getSourceAsString(), ItemRowsDto.class);
            //远程调用
            rowsDto.setAreaName(vo.getAreaId()==1? "北京":"上海");
            rowsDto.setAddress(vo.getAreaId()==1? "北京" +
                    "":"上海");
            rowsDto.setImgUrl(
                    imageFeign.image(rowsDto.getId(),1L,1L)==null? "https://s1.ax1x.com/2022/08/23/vcYwLD.png" :
                            imageFeign.image(rowsDto.getId(),1L,1L).getImgUrl());
//            rowsDto.setImgUrl("https://s1.ax1x.com/2022/08/23/vcYwLD.png");
            if(vo.getKeyword()!=null && !vo.getKeyword().trim().equals("")) {
                //拿到经过高亮处理的字段
                rowsDto.setItemName(StringUtils.arrayToDelimitedString(searchHits[i].getHighlightFields().get("itemname").getFragments(), ""));
                rowsDto.setAbstractMessage(StringUtils.arrayToDelimitedString(searchHits[i].getHighlightFields().get("abstractmessage").getFragments(), ""));
            }
            resultDto.getRows().add(rowsDto);
        }

        return resultDto;
    }


    @Override//详情页面演出时间
    public CommonResponse<List<DmScheduler>> getTimePlan(String itemId) {
        List<DmScheduler> list = schedulerFeign.dmScheduler(itemId);
        return ResponseUtils.returnSuccess(list);
    }


    @Override//详情页面票价格
    public CommonResponse<List<SchedulerPeiceDto>> getPrice(String schedulerId) {

        List<DmSchedulerSeatPrice> list = schedulerFeign.dmSchedulerPrice(schedulerId);

        List<SchedulerPeiceDto> dmSchedulerSeatPriceList = itemsDtoMapper.schedulerPeiceDtos(list);
        List<SchedulerPeiceDto> dto = new ArrayList<>();
        for (SchedulerPeiceDto s: dmSchedulerSeatPriceList) {
            if(s.getSeatNum()>0){
                s.setIsHaveSeat(1L);
            }
            dto.add(s);
        }

        return ResponseUtils.returnSuccess(dto);
    }

}
